package com.jet.chat.server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import com.jet.chat.exception.ChatExceptionCheckAuthSQLException;
import com.jet.chat.exception.ChatExceptionCommandClassNotFound;
import com.jet.chat.exception.ChatExceptionCommandIllegalAccess;
import com.jet.chat.exception.ChatExceptionCommandInstantiation;
import com.jet.chat.exception.ChatExceptionMessageRead;
import com.jet.chat.exception.ChatExceptionSessionReaderNotAvailable;
import com.jet.chat.exception.ChatExceptionSessionWriterNotAvailable;
import com.jet.chat.service.ChatAccessService;
import com.jet.chat.service.ChatMessage;
import com.jet.chat.service.ChatMessageService;


public class ChatSession implements Runnable {
	private ChatServer chatServer;
	private Socket socket;
	private BufferedReader reader;
	private PrintWriter writer;
	private int id;
	private String username;
	private String channelName;
	
	public ChatSession(ChatServer chatServer, String channelName, Socket socket) throws ChatExceptionSessionReaderNotAvailable, ChatExceptionSessionWriterNotAvailable, ChatExceptionMessageRead {
		this.chatServer = chatServer;
		this.channelName = channelName;
		this.socket = socket;
		
		try {
			this.reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		} catch (IOException e) {
			throw new ChatExceptionSessionReaderNotAvailable("поток чтения не доступен");
			//e.printStackTrace();
		}
		
		try {
			this.writer = new PrintWriter(socket.getOutputStream());
		} catch (IOException e) {
			throw new ChatExceptionSessionWriterNotAvailable("поток вывода не доступен");
			//e.printStackTrace();
		}
		
	}
	
	public PrintWriter getWriter() {
		return writer;
	}

	public int getId() {
		return id;
	}

	public String getUsername() {
		return username;
	}
	
	public String getChannelName() {
		return channelName;
	}
	
	public void setChannelName(String channelName) {
		this.channelName = channelName;
	}

	@Override
	public void run() {
		ChatAccessService chatAccessService = new ChatAccessService(chatServer.getDbService());
		
		try {
			chatAccessService.checkAuth(reader, writer);
			this.id = chatAccessService.getId();
			this.username = chatAccessService.getUsername();
			
			if (this.id != 0) {
				chatServer.getChannel(channelName).addSession(this);
				
				ChatMessage chatMessage = null;
				try {
					while(!socket.isClosed()) {
						chatMessage = new ChatMessage(reader);
						proceed(chatMessage);
					}
				} catch (ChatExceptionMessageRead e) {
					// TODO Auto-generated catch block
					//e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					//e.printStackTrace();
				} finally {
					chatServer.getChannel(channelName).removeSession(this);
				}
			}
		} catch (ChatExceptionMessageRead e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (ChatExceptionCheckAuthSQLException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

	}
	
	private synchronized void proceed(ChatMessage chatMessage) throws ChatExceptionMessageRead, IOException {
		if (socket.isClosed()) {
			System.out.println("socket.isClosed()");
		} else {
			if (chatMessage == null) {
				socket.close();
				System.out.println("chatMessage == null");
			} else {
				if (chatMessage.getMessage() == null) {
					socket.close();
					System.out.println("chatMessage.getMessage() == null");
				} else {
					try {
						ChatMessageService.proceed(chatServer, this, chatMessage);
					} catch (ChatExceptionCommandClassNotFound e) {
						e.printStackTrace();
					} catch (ChatExceptionCommandInstantiation e) {
						e.printStackTrace();
					} catch (ChatExceptionCommandIllegalAccess e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
	
}
